#pragma once

// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows 200.
#define _WIN32_WINNT 0x0500     // Change this to the appropriate value to target other versions of Windows.
#endif

#define WIN32_LEAN_AND_MEAN     // Exclude rarely-used stuff from Windows headers
#define STRICT
#define NOMINMAX
#define _CRT_SECURE_NO_WARNINGS

// Active Template Library
//

#ifdef DEBUG
#define _ATL_DEBUG_INTERFACES 1
#endif

#define _ATL_APARTMENT_THREADED
#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
#include <atlwin.h>

// Windows Template Library
//
#define max std::max
#define min std::min
#include <wtl/atlapp.h>
#include <wtl/atlctrls.h>
#include <wtl/atldlgs.h>
#include <wtl/atlmisc.h>
#undef max
#undef min

#include <time.h>
#include <stdio.h>

typedef INT8  SInt8;
typedef INT16 SInt16;
typedef INT32 SInt32;
typedef INT64 SInt64;

typedef UINT8  UInt8;
typedef UINT16 UInt16;
typedef UINT32 UInt32;
typedef UINT64 UInt64;

#define AtomicIncrement(__ptr) InterlockedIncrement((LONG*)__ptr)
#define AtomicDecrement(__ptr) InterlockedDecrement((LONG*)__ptr)
#define snprintf _snprintf

#define _HTL_NO_AUTOMATIC_NAMESPACE
#include "htl/htl.h"

class CAutoLock
{
	CRITICAL_SECTION m_cs;
	
public:

	CAutoLock()
	{
		InitializeCriticalSection(&m_cs);
	}

	~CAutoLock()
	{
		DeleteCriticalSection(&m_cs);
	}
	
	inline void Lock()
	{
		EnterCriticalSection(&m_cs);
	}
	
	inline bool TryLock()
	{
		return !!TryEnterCriticalSection(&m_cs);
	}
	
	inline void Unlock()
	{
		LeaveCriticalSection(&m_cs);
	}

	inline void AssertLocked() const
	{
#ifndef _WIN64
		
		// If you got this assertion you should replace
		//
		// resp.Foo();
		//
		// with
		//
		// resp.Lock();
		// resp.Foo();
		// resp.Unlock();
		//
		
		DWORD dwVersion = ::GetVersion();
		
		// On Win2k/XP RTL_CRITICAL_SECTION fields do match their names.
		//
		if (LOWORD(dwVersion) == 0x0005 || LOWORD(dwVersion) == 0x0105)
		{
			_ASSERTE(m_cs.LockCount >= 0 && m_cs.OwningThread == (HANDLE)(DWORD_PTR)::GetCurrentThreadId());
		}
#endif
	}
};
